package eval

import (
	"showen/lex"
	"showen/obj"
	"showen/parse"
	"testing"
)

// (complex? 3+4i)= ⇒ #t
// (complex? 3)= ⇒ #t
// (real? 3)= ⇒ #t
// (real? -2.5+0.0i)= ⇒ #t
// (real? #e1e10)= ⇒ #t
// (rational? 6/10)= ⇒ #t
// (rational? 6/3)= ⇒ #t
// (integer? 3+0i)= ⇒ #t
// (integer? 3.0)= ⇒ #t
// (integer? 8/4)= ⇒ #t
func TestNumberTypeIntegration(t *testing.T) {
	tests := []struct {
		input string
		want  []string
	}{
		{
			"(integer? 42)",
			[]string{"#t"},
		},
		{
			"(rational? 42)",
			[]string{"#t"},
		},
		{
			"(real? 42)",
			[]string{"#t"},
		},
		{
			"(complex? 42)",
			[]string{"#t"},
		},
		{
			"(rational? 1/42)",
			[]string{"#t"},
		},
		{
			"(real? 1/42)",
			[]string{"#t"},
		},
		{
			"(complex? 1/42)",
			[]string{"#t"},
		},
		{
			"(real? 1.42)",
			[]string{"#t"},
		},
		{
			"(complex? 1.42)",
			[]string{"#t"},
		},
		{
			"(real? 1.42+0.0i)",
			[]string{"#t"},
		},
	}

	env := obj.NewEnvironment()
	RegisterBuiltinProcedures(env)

	for _, tt := range tests {
		lexer := lex.NewLexer(tt.input)
		tokens := lexer.ReadTokens()
		parser := parse.NewParser(tokens)
		exprs, err := parser.ParseProgram()
		if err != nil {
			t.Errorf("ParseProgram() error = %v", err)
			continue
		}
		for i, expr := range exprs {
			obj, err := EvalExpression(expr, env)
			if err != nil {
				t.Errorf("Eval() error = %v", err)
				continue
			}
			if obj.Inspect() != tt.want[i] {
				t.Errorf("For input %q: Eval() = %v, want %v", tt.input, obj.Inspect(), tt.want[i])
			}
		}
	}
}
